﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "ISurface.h"
#include "Vector3d.h"

namespace gcmp
{

    /// \brief Nurbs曲面的控制点
    struct NurbsSurfaceCtrlPt3d
    {
        Vector3d Point;   // 点的位置
        double Weight = 1;    //  权
    };

    /// \brief v方向的Vector3d数组定义
    typedef std::vector<Vector3d> VDirVector3dArr;
    /// \brief u方向的Vector3d的二维数组定义
    typedef std::vector<VDirVector3dArr> UDirVector3dArrArr;

    /// \brief NURBS曲面
    ///
    class INurbsSurface : public ISurface
    {
        DEFINE_CAST_DERIVED(gcmp::INurbsSurface, gcmp::ISurface);
    public:
        /// \brief 构造多片组合的Hermite曲面
        ///
        /// 假设有m+1个u参数，n+1个v参数，那么插值点数组分布如下（u、v向偏导，uv混合导数数组顺序类似)
        /// [0][0], [0][1], ...,   [0][n-1],  [0][n]        ---------> v向
        /// [1][0], [1][1], ...,   [1][n-1],  [1][n]        |       
        ///                                                 |
        /// [m-1][0],[m-1][1], ...,[m-1][n-1], [m-1][n]     |
        /// [m][0], [m][1], ...,   [m][n-1], [m][n]        \|/ u向
        ///
        /// \param uParameters    u方向插值点的参数
        /// \param vParameters    v方向插值点的参数
        /// \param interpolationPoints  插值点的位置
        /// \param uInterpolationPointsDerivative  插值点的u向偏导
        /// \param vInterpolationPointsDerivative  插值点的v向偏导
        /// \param uvInterpolationPointsDerivative 插值点的混合偏导
        /// \return Nurbs曲面
        GCMP_GEOMETRY_INTERFACE_EXPORT static OwnerPtr<INurbsSurface> CreateMultiHermiteSurface(
            const std::vector<double>& uParameters,
            const std::vector<double>& vParameters,
            const UDirVector3dArrArr& interpolationPoints,
            const UDirVector3dArrArr& uInterpolationPointsDerivative,
            const UDirVector3dArrArr& vInterpolationPointsDerivative,
            const UDirVector3dArrArr& uvInterpolationPointsDerivative);

        /// \brief  构造插值曲面
        ///
        /// 假设有m+1个u参数，n+1个v参数，那么插值点数组分布如下
        /// [0][0], [0][1], ...,   [0][n-1],  [0][n]        ---------> v向
        /// [1][0], [1][1], ...,   [1][n-1],  [1][n]        |       
        ///                                                 |
        /// [m-1][0],[m-1][1], ...,[m-1][n-1], [m-1][n]     |
        /// [m][0], [m][1], ...,   [m][n-1], [m][n]        \|/ u向
        ///
        /// \param uParameters    u方向插值点的参数
        /// \param vParameters    v方向插值点的参数
        /// \param interpolationPoints  插值点的位置
        /// \return Nurbs曲面
        GCMP_GEOMETRY_INTERFACE_EXPORT static OwnerPtr<INurbsSurface> CreateInterpolateSurface(
            const std::vector<double>& uParameters,
            const std::vector<double>& vParameters,
            const UDirVector3dArrArr& interpolationPoints);


        /// \brief  构造Nurbs曲面
        ///
        /// 假设有m+1个u参数，n+1个v参数，那么控制点数组分布如下
        /// [0][0], [0][1], ...,   [0][n-1],  [0][n]        ---------> v向
        /// [1][0], [1][1], ...,   [1][n-1],  [1][n]        |       
        ///                                                 |
        /// [m-1][0],[m-1][1], ...,[m-1][n-1], [m-1][n]     |
        /// [m][0], [m][1], ...,   [m][n-1], [m][n]        \|/ u向
        ///
        /// \param degreeU     u方向次数
        /// \param degreeV     v方向次数
        /// \param countU      u方向控制点数
        /// \param countV      v方向控制点数
        /// \param uKnots      u方向节点向量
        /// \param vKnots      v方向节点向量
        /// \param weights     控制点权值列表
        /// \param ctrlPoints  控制点数组
        /// \return Nurbs曲面
        GCMP_GEOMETRY_INTERFACE_EXPORT static OwnerPtr<INurbsSurface> Create(
            int degreeU,int degreeV,
            int countU, int countV,
            const std::vector<double>& uKnots,
            const std::vector<double>& vKnots,
            const std::vector<double>& weights,
            const UDirVector3dArrArr& ctrlPoints);
    public:
        /// \brief 析构函数
        virtual ~INurbsSurface() {}

        /// \brief 获得NURBS曲面U向次数
        /// \return NURBS曲面U向次数
        virtual int GetDegreeU() const = 0;

        /// \brief 获得NURBS曲面V向次数
        /// \return NURBS曲面V向次数
        virtual int GetDegreeV() const = 0;

        /// \brief 获得NURBS曲面U向控制点个数
        /// \return NURBS曲面U向控制点个数
        virtual int GetControlPointCountU() const = 0;

        /// \brief 获得NURBS曲面V向控制点个数
        /// \return NURBS曲面V向控制点个数
        virtual int GetControlPointCountV() const = 0;

        /// \brief 根据索引获得NURBS曲面控制点
        /// \param indexU NURBS曲面U向控制点索引
        /// \param indexV NURBS曲面V向控制点索引
        /// \param controlPoint NURBS曲面控制点
        /// \param weight NURBS曲面控制点权数
        /// \return 无
        virtual void GetControlPoint(int indexU, int indexV, Vector3d &controlPoint, double &weight) const = 0;

        /// \brief 获得NURBS曲面U向节点数组
        /// \param uKnots NURBS曲线U向节点数组
        /// \return 无
        virtual void GetKnotsU(std::vector<double> &uKnots) const = 0;

        /// \brief 获得NURBS曲面V向节点数组
        /// \param vKnots NURBS曲线V向节点数组
        /// \return 无
        virtual void GetKnotsV(std::vector<double> &vKnots) const = 0;

        /// \brief 设置在索引处的控制顶点
        /// \param indexU NURBS曲面U向控制点索引
        /// \param indexV NURBS曲面V向控制点索引
        /// \param controlPoint NURBS曲面控制点
        /// \param weight NURBS曲面控制点权数
        /// \return 成功返回true，失败返回false
        virtual bool SetControlPoint(int indexU, int indexV, const Vector3d& controlPoint, double weight) = 0;

        /// \brief  设置Nurbs曲面在索引处的U向节点
        /// \param  uKnotsIndex  节点索引
        /// \param  uKnot     U向节点
        /// \return 成功返回true，失败返回false
        virtual bool SetKnotU(int uKnotsIndex, double uKnot) = 0;

        /// \brief  设置Nurbs曲面在索引处的V向节点
        /// \param  vKnotsIndex  节点索引
        /// \param  vKnot     U向节点
        /// \return 成功返回true，失败返回false
        virtual bool SetKnotV(int vKnotsIndex, double vKnot) = 0;

        /// \brief  插入u向节点
        /// \param uKnot  节点参数
        // \param  count  插入节点的个数
        /// \return 成功返回true，失败返回false
        virtual bool InsertKnotsU(double uKnot, int count) = 0;

        /// \brief  插入v向节点
        /// \param  vKnot  节点参数
        // \param   count  插入节点的个数
        /// \return 成功返回true，失败返回false
        virtual bool InsertKnotsV(double vKnot, int count) = 0;
    };
}
